<template>
  <div class="login">
    <vue-particles
        id="tsParticles"
        :options="options"
        :particlesInit="particlesInit"
        :particlesLoaded="particlesLoaded"
        class="login_particles"
    />
    <div class="loginPart">
      <h2>用户登录</h2>
      <el-form
          ref="loginFormRef"
          :model="loginForm"
          :rules="loginFormRules"
          class="demo-ruleForm"
          label-width="100px"
          status-icon
          style="transform:translate(-30px);"
          @submit.prevent
      >
        <el-form-item label="账号：" prop="account">
          <el-input v-model="loginForm.username" clearable maxlength="20" placeholder="请输入账号"/>
        </el-form-item>
        <el-form-item label="密码：" prop="password">
          <el-input v-model="loginForm.password" clearable maxlength="20" placeholder="请输入密码" show-password
                    type="password" @keyup.enter="handleLoginForm(loginFormRef)"/>
        </el-form-item>
        <el-form-item v-show="captchaEntity.enabled" label="验证码：" prop="captchaCode">
          <el-input v-model="loginForm.captchaCode" clearable maxlength="4" placeholder="请输入验证码"
                    style="width: 150px;" @keyup.enter="handleLoginForm(loginFormRef)">
            <!--            <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />-->
          </el-input>
          <div class="login-code">
            <img :src="captchaImageUrl" class="login-code-img" @click="resetCaptchaCode">
          </div>
        </el-form-item>
        <el-button :loading="loading" class="btn" type="primary" @click="handleLoginForm(loginFormRef)">
          <span v-if="!loading">登 录</span>
          <span v-else>登 录 中...</span>
        </el-button>
        <!--        <div style="text-align: right;transform:translate(0,30px);">-->
        <!--          <el-link type="warning" @click="changeRegist">没有账号？去注册</el-link>-->
        <!--        </div>-->
      </el-form>
    </div>
    <div class="footer">
      <span>Copyright © 2025 xhai. All Rights Reserved.</span>
    </div>
  </div>
</template>

<script lang="ts" setup>
/***********************import**********************/
import {reactive, ref, onMounted} from 'vue'
import router from '../router'
import {login, getCaptchaCode} from '../api/login'
import useStore from '../store'
import {type LoginForm} from '../model/login/LoginForm.ts'
import {ElMessage, type FormInstance} from 'element-plus'
// import { loadFull } from 'tsparticles'
import {loadSlim} from "tsparticles-slim"
import {type Container} from 'tsparticles-engine'
import {type Engine} from 'tsparticles-engine'
import {type CaptchaEntity} from '../model/login/CaptchaEntity.ts'
import {Constants} from '../constant/Constants.ts'
import type {ResponseResult} from "../model/common/ResponseResult.ts";
import {HybridEncryptHelper, publicKey} from "../utils/tsencrypt.ts";

/**********************variable*********************/
// 验证码实体
let captchaEntity = reactive<CaptchaEntity>({
  uuid: '',
  mode: '',
  image: '',
  enabled: true
})
// 验证码图片url
let captchaImageUrl = ref<string>()

//登录表单绑定
const loginFormRef = ref<FormInstance>()
// 登录表单
const loginForm: LoginForm = reactive<LoginForm>({
  username: '',
  password: '',
  captchaCode: '',
  captchaUuid: '',
  aesSecretKey: ''
})

// 用户名校验
const validateUsername = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请输入账号'))
  } else {
    callback()
  }
}
// 密码校验
const validatePassword = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请输入密码'))
  } else {
    callback()
  }
}
// 验证码校验
const validateCaptchaCode = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请输入验证码'))
  } else {
    callback()
  }
}
//登陆表单校验规则
const loginFormRules = reactive({
  username: [{validator: validateUsername, trigger: 'blur'}],
  password: [{validator: validatePassword, trigger: 'blur'}],
  captchaCode: [{validator: validateCaptchaCode, trigger: 'blur'}],
})
// 存储
const store = useStore()
// 登录加载
let loading = false

/*******************method*******************/
// 重置验证码
const resetCaptchaCode = () => {
  getCaptchaCode().then(res => {
    const result: ResponseResult = res.data
    if (result.code === Constants.REQUEST_SUCCESS_CODE) {
      // 更新现有对象的属性，保持响应式
      Object.assign(captchaEntity, result.data)
      if (captchaEntity.enabled) {
        captchaImageUrl.value = 'data:image/gif;base64,' + captchaEntity.image
        loginForm.captchaUuid = captchaEntity.uuid
      }
    } else {
      ElMessage.error(result.msg)
    }
  }).catch((error) => {
    Promise.reject(error)
  });
}
// 组件加载完后
onMounted(() => {
  resetCaptchaCode()
})

// // 跳转注册
// const changeRegist = () => {
//   router.replace('/regist')
// }

// 提交登陆表单
const handleLoginForm = async (formEl: FormInstance | undefined) => {
  if (formEl != undefined)
    return formEl.validate(async (valid) => {
      if (valid) {
        loading = true
        // 加密
        const sendLoginForm: LoginForm = {...loginForm}

        const helper = new HybridEncryptHelper();
        helper.setRsaPublicKey(publicKey);
        // 生成AES密钥
        helper.generateAesKey(256);
        // 遍历参数加密数据
        const encryptedSendLoginForm: LoginForm = await helper.encryptFormDataToBase64AES(sendLoginForm);
        // 将AES密钥通过RSA密钥加密
        encryptedSendLoginForm.aesSecretKey = helper.encryptAesKeyToBase64()
        await login(loginForm).then((res) => {
          const result: ResponseResult = res.data
          if (result.code === Constants.REQUEST_SUCCESS_CODE) {
            ElMessage({
              message: '登录成功',
              type: 'success'
            })
            // 把信息存储到全局变量中
            store.setToken(result.data.token)
            // 2. 跳转到后台首页！！！
            router.push('/home')
          } else {
            loading = false
            ElMessage.error(result.msg)
          }
        }).catch((error) => {
          loading = false
          return Promise.reject(error)
        })
      } else {
        ElMessage.error("错误的提交！")
      }
    })
}

/******************particles******************/
// 初始化
const particlesInit = async (engine: Engine) => {
  // await loadFull(engine);
  await loadSlim(engine);
}
// 加载
const particlesLoaded = async (container: Container) => {
  console.log("Particles container loaded", container);
}
// 参数
const options = {
  fpsLimit: 60,
  interactivity: {
    detectsOn: 'canvas',
    events: {
      onClick: { // 开启鼠标点击的效果
        enable: true,
        mode: 'push'
      },
      onHover: { // 开启鼠标悬浮的效果(线条跟着鼠标移动)
        enable: true,
        mode: 'grab'
      },
      resize: true
    },
    modes: { // 配置动画效果
      bubble: {
        distance: 400,
        duration: 2,
        opacity: 0.8,
        size: 40
      },
      push: {
        quantity: 4
      },
      grab: {
        distance: 200,
        duration: 0.4
      },
      attract: { // 鼠标悬浮时，集中于一点，鼠标移开时释放产生涟漪效果
        distance: 200,
        duration: 0.4,
        factor: 5
      }
    }
  },
  particles: {
    color: {
      value: '#BA55D3' // 粒子点的颜色
    },
    links: {
      color: '#FFBBFF', // 线条颜色
      distance: 150,//线条距离
      enable: true,
      opacity: 0.4, // 不透明度
      width: 1.2 // 线条宽度
    },
    collisions: {
      enable: true
    },
    move: {
      attract: {enable: false, rotateX: 600, rotateY: 1200},
      bounce: false,
      direction: 'none',
      enable: true,
      out_mode: 'out',
      random: false,
      speed: 0.5, // 移动速度
      straight: false
    },
    number: {
      density: {
        enable: true,
        value_area: 800
      },
      value: 80//粒子数
    },
    opacity: {//粒子透明度
      value: 0.7
    },
    shape: {//粒子样式
      type: 'star'
    },
    size: {//粒子大小
      random: true,
      value: 3
    }
  },
  detectRetina: true
}
</script>
<style scoped>
.footer {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  padding: 10px;
  background-color: #FFF0F5;
  text-align: center;
  font-size: 12px;
  color: #999;
}

.login {
  height: 100%;
  width: 100%;
  overflow: hidden;
}

.login_particles {
  height: 100%;
  width: 100%;
  background-size: cover;
  background-repeat: no-repeat;
  background-image: url('../assets/loginBackground.png');
  opacity: 0.9;
  position: absolute;
  pointer-events: none;
}

.loginPart {
  position: absolute;
  /*定位方式绝对定位absolute*/
  top: 50%;
  left: 80%;
  /*顶和高同时设置50%实现的是同时水平垂直居中效果*/
  transform: translate(-50%, -50%);
  /*实现块元素百分比下居中*/
  width: 450px;
  padding: 50px;
  background: rgba(255, 204, 255, .3);
  /*背景颜色为黑色，透明度为0.8*/
  box-sizing: border-box;
  /*box-sizing设置盒子模型的解析模式为怪异盒模型，
  将border和padding划归到width范围内*/
  box-shadow: 0px 15px 25px rgba(0, 0, 0, .5);
  /*边框阴影  水平阴影0 垂直阴影15px 模糊25px 颜色黑色透明度0.5*/
  border-radius: 15px;
  /*边框圆角，四个角均为15px*/
}

.login-code {
  width: 33%;
  height: 38px;
  float: right;

  img {
    cursor: pointer;
    vertical-align: middle;
  }
}

.login-code-img {
  height: 38px;
}

h2 {
  margin: 0 0 30px;
  padding: 0;
  color: #fff;
  text-align: center;
  /*文字居中*/
}

.btn {
  transform: translate(170px);
  width: 80px;
  height: 40px;
  font-size: 15px;
}
</style>
